package com.dycong.common.common;

import org.apache.log4j.Logger;

import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * Created by ${dycong} on 2016/12/27.
 */
public class MySignUtil {

    private static Logger logger = Logger.getLogger(MySignUtil.class);

    private static final char[] hexCode;

    static {
        hexCode = "0123456789ABCDEF".toCharArray();
    }


    /**
     * @see 得到MD5的byte[]数组的长度32的十六进制数的字符串
     */
    public static String getMd5Hex(byte[] bytes) {
        byte[] md5Bytes = getMd5(bytes);
        return printHexBinary(md5Bytes);
    }

    /**
     * @see 得到MD5的byte[]数组
     */
    public static byte[] getMd5(byte[] bytes) {
        try {
            MessageDigest e = MessageDigest.getInstance("MD5");
            byte[] md5 = e.digest(bytes);
            return md5;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("NoSuchAlgorithmException", e);
        }
    }

    /**
     * @see 生成MD5并转换为32长度的十六进制数字符串
     */
    public static String getMd5Hex(String str){
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            logger.debug("NoSuchAlgorithmException caught!");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        byte[] byteArray = messageDigest.digest();

        StringBuffer md5StrBuff = new StringBuffer();
        for (byte b : byteArray) {
            md5StrBuff.append(hexCode[b >> 4 & 0xf]);
            md5StrBuff.append(hexCode[b & 0xf]);
        }
        return md5StrBuff.toString();
    }

    /**
     *@see SHA1加密!!!
     *@see 返回数组size为20,MD5是生成16位数组
     * @param source
     * @return
     */
    public static byte[] getSHA1(byte[] source) {
        MessageDigest crypt = null;
        try {
            crypt = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        crypt.reset();
        crypt.update(source);
        return crypt.digest();
    }

    public static String getSHA1Str(byte[] source) {
        MessageDigest crypt = null;
        try {
            crypt = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException var3) {
            throw new RuntimeException(var3);
        }
        crypt.reset();
        crypt.update(source);
        return toHexString(crypt.digest());
    }


    /**
     * @see byte数组转为16进制数
     * @see 每个字节8位ascii码,分别取高四位底四位(通过移位>>与与运算&1111),将每一个单字节char拆分为两个十六进制数
     * hexCode = "0123456789ABCDEF".toCharArray()
     * r.append(hexCode[(b >> 4) & 0xF]);
     * r.append(hexCode[(b & 0xF)]);
     */
    public static String toHexString(byte[] bytes) {
        return DatatypeConverter.printHexBinary(bytes).toUpperCase();
    }

    /**
     * @see byte数组转为16进制数
     */
    public static String printHexBinary(byte[] data) {
        StringBuilder r = new StringBuilder(data.length * 2);
        for (byte b : data) {
            r.append(hexCode[(b >> 4) & 0xF]);
            r.append(hexCode[(b & 0xF)]);
        }
        return r.toString();
    }

    /**
     * @see 判断是否包含NULL或“”
     */
    public static boolean existEmptyString(String... strings) {
        return strings == null ? false : Arrays.stream(strings).filter((s) -> {
            return s == null || s.equals("");
        }).findAny().isPresent();
    }

    /**
     * @see 验证手机号
     */
    public static boolean isPhoneNumber(String string) {
        return string.matches("^1[34578]\\d{9}$");
    }

    public static boolean isContainEmpty(String... args) {
        return !containEmpty(args);
    }

    /**
     * @see 数组包含“”或者NULL
     */
    public static boolean containEmpty(String... args) {
        return findEmpty(args).isPresent();
    }

    private static Optional<String> findEmpty(String... args) {
        return ((Stream) Arrays.stream(args).parallel()).map((s) -> {
            return s == null ? "" : s;
        }).filter(s -> s.equals("")).findAny();
    }

    public static byte[] convertStringEncoding(String string, String encoding) throws UnsupportedEncodingException {
        return string.getBytes(encoding);
    }

    public static String format(Date date, String formatString) {
        return new SimpleDateFormat(formatString).format(date);
    }

    public static Optional<Date> parse(String dateString, String formatString) {
        try {
            return Optional.of(new SimpleDateFormat(formatString).parse(dateString));
        }catch (ParseException e){
            logger.debug("parse日期异常",e);
            return Optional.empty();
        }
    }
    /**
     * @see Base64是一种基于64个可打印字符来表示二进制数据的表示方法.由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。
     */
    public static String toBase64(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static byte[] fromBase64(String base64) {
        return Base64.getDecoder().decode(base64);
    }



    /*
    public static LocalDateTime toLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        return LocalDateTime.from(instant);
    }
    public static Date fromLocalDateTime(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    @org.junit.Test
    public void t(){
        System.out.println(toLocalDateTime(new Date()));
    }*/

}
